#include <stdio.h>
#include <stdbool.h>
#include <malloc.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/select.h>
#include <semaphore.h>
#include <time.h>
#include <signal.h>
#include <setjmp.h>

#include "interaction.h"
#include "app.h"
#include "log.h"
#include "ticket_device.h"
#include "user_device.h"

#include "ring_buffer.h"
#include "gtk_buffer.h"
#include "communication_core.h"

static struct app app;
extern jmp_buf buf;

static void *gtk_thread(void *arg);
static void *destroy_thread(void *arg);
static void *server_work_thread(void *arg);
static void *server_recv_thread(void *ring_buffers);
static void deal_ctrl_c(int sig);

/**
 * @brief   初始化
 */
func_t *init(func_t *p_func)
{
    int ret, count = 0;

    app.interaction = (struct interaction *)malloc
                        (sizeof(struct interaction));
    if (!app.interaction) {
        DEBUG("MALLOC ERROR!");
        return NULL;
    }
    init_gtk();

    /* 管理员链表和信息初始化 */
    /* app.interaction->admin = (struct admin *)malloc(sizeof(struct admin));
    if (!app.interaction->admin) {
        DEBUG("MALLOC ERROR!");
        return NULL;
    }
    admin_init(app.interaction->admin); */

    /* 车票链表和信息初始化 */
    ret = ticket_init(&app.interaction->ticket_head,
                        &app.interaction->user_ticket_head);
    if (ret != true) {
        return NULL;
    }

    /* 用户链表和信息初始化 */
    ret = user_init(&app.interaction->user_head);
    if (ret != true) {
        DEBUG("USER INIT ERROR!");
        return NULL;
    }

    /*初始化心跳包的结构体*/
    for (count = 0; count <= 10; count++) {
        app.heart_bag.last_heart_time[count] = 0;
        app.heart_bag.heart_fd[count] = 0;
        app.heart_bag.is_data[count] = 0;
    }

    /* 初始化缓冲区 */
    app.ring_buffers.to_recv_pthread_fd = ring_buffer_alloc((sizeof(int) * 10));
    if (!app.ring_buffers.to_recv_pthread_fd)
        return (NULL);
    app.ring_buffers.recv_data = ring_buffer_alloc((sizeof(struct data_packet) * 10));
    if (!app.ring_buffers.recv_data)
        return (NULL);

    /* 线程同步初始化 */
    sem_init(&sem, 0, 0);
    sem_init(&sem_find_ticket, 0, 1);
    sem_init(&sem_ack, 0, 1);

    sem_init(&sem_ticket, 0, 1);
    sem_init(&sem_user, 0, 1);
    sem_init(&sem_user_ticket, 0, 1);
    sem_init(&sem_destroy1, 0, 0);
    sem_init(&sem_run, 0, 0);
    
    /*创建GTK线程*/
    ret = pthread_create(&app.server_pthreads.gtk_thread, NULL, 
                        gtk_thread, NULL);
    if (ret != 0) {
        DEBUG("GTK线程创建失败\r\n");
        return (NULL);
    }
    /*创建销毁线程*/
    ret = pthread_create(&app.server_pthreads.destroy_thread, NULL, 
                        destroy_thread, NULL);
    if (ret != 0) {
        DEBUG("销毁线程创建失败\r\n");
        return (NULL);
    }

    /*创建接收线程*/
    ret = pthread_create(&app.server_pthreads.recv_thread, NULL, 
                        server_recv_thread, &app.ring_buffers);
    if (ret != 0) {
        DEBUG("接收线程创建失败\r\n");
        return (NULL);
    }
    /*创建工作线程*/
    for (count = 0; count < MAX_WORK_THREAD_NUM; count++) {
        ret = pthread_create(&app.server_pthreads.work_thread[count], NULL, 
                        server_work_thread, NULL);
        if (ret != 0) {
            DEBUG("工作线程创建失败\r\n");
            return (NULL);
        }
    }

    signal(SIGINT, deal_ctrl_c);
    sem_wait(&sem_run);
    CLEAR();
    input_buffer("Linux服务端初始化完成\n");
    printf("Linux服务端初始化完成\r\n");

    return p_func;
}

/**
 *  监听客户端连接请求
 */
int run(void)
{
    int server_fd, client_fd;
    int i;
    struct sockaddr_in client_addr;
    socklen_t remote_sin_size = sizeof(struct sockaddr_in);
    struct communication_core communication;
    time_t now_time;

    communication_core_init(&communication);
    communication.dev.cmd = COMM_SERVER_INIT;
    server_fd = communication.ioctl(&communication.dev, 
                          communication.dev.cmd, communication.dev.arg);

    while (1) {
        /*accept()函数监听客户端的连接请求 */
        client_fd = accept(server_fd, 
                          (struct sockaddr*)&client_addr, 
                          &remote_sin_size);
        if (client_fd == -1) {
            perror("accept error\r\n");
            DEBUG("ACCEPT ERROR\r\n");
            continue;
        }

        /*给连接进来的客户端赋予心跳包的初始时间*/
        time(&now_time);
        for (i = 0; i < 10; i++) {
            if (app.heart_bag.is_data[i] == 0) {
                app.heart_bag.is_data[i] = 1;
                app.heart_bag.heart_fd[i] = client_fd;
                app.heart_bag.last_heart_time[i] = now_time;

                break;
            }
        }
        /* 连接客户端后，将接入服务端客户端的fd写入缓冲区 */
        ring_buffer_put(app.ring_buffers.to_recv_pthread_fd, (char *)&client_fd, sizeof(int));
    }

    communication_core_destory(&communication);
}

void *gtk_thread(void *arg)
{   
    /*运行gtk界面*/
    gtk_main();

    return arg;
}

void *destroy_thread(void *arg)
{
    int ret;
    
    sem_wait(&sem_destroy1);

    sem_wait(&sem_user);
    system("clear");
    /*保存用户信息，销毁申请的内存*/
    ret = user_destroy(&((app).interaction->user_head));
    if (ret != true) {
        DEBUG("USER DESTROY ERROR!");
        return false;
    }
    sem_post(&sem_user);

    sem_wait(&sem_ticket);
    sem_wait(&sem_user_ticket);
    /*保存车票信息，销毁申请的内存*/
    ret = ticket_destroy(&(app.interaction->ticket_head),
                            &(app.interaction->user_ticket_head));
    if (ret != true) {
        DEBUG("TICKET DESTROY ERROR!");
        return false;
    }
    sem_post(&sem_ticket);
    sem_post(&sem_user_ticket);

    //admin_destroy(app.interaction->admin);

    free(app.interaction);

    return arg;
}

/**
 * 监听客户端发过来的数据
 */
static void *server_recv_thread(void *ring_buffers)
{
    struct ring_buffer *to_recv_pthread_fd = NULL;
    struct ring_buffer *recv_data = NULL;
    fd_set all_setfd;
    int clientfd_tmp = -1;
    int all_clientfd[MAX_SELECT_NUM], maxfd = 0;
    char temp_buf[100] = {0};
    int clientfd_sum = 0;
    int count = 0, count1 = 0;
    int ret = 0;
    struct timeval timeout;
    struct communication_core communication;
    struct data_with_fd data_tmp;
    time_t now_time;
    int i;
    int should_continue = 0;
    int last_fd_is_disconnect = 0;

    if (!ring_buffers) {
        DEBUG("PARAM ERROR!\n");
        pthread_exit((void *)(NULL));
    }

    communication_core_init(&communication);
    communication.dev.cmd = COMM_RECV;
    to_recv_pthread_fd = ((struct ring_buffers*)ring_buffers)->to_recv_pthread_fd;
    recv_data = ((struct ring_buffers*)ring_buffers)->recv_data;
    FD_ZERO(&all_setfd);
    for (count = 0; count < MAX_SELECT_NUM; count++)
        all_clientfd[count] = -1;
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;
    reset_data_packet(&data_tmp.data);

    while (1) {
        /*当fd的缓冲区有数据，且客户端的连接数量小于预设数量时，将客户端接入*/
        if (clientfd_sum < MAX_SELECT_NUM) {
            while ((ring_buffer_len(to_recv_pthread_fd) >= sizeof(int))) {
                ring_buffer_get(to_recv_pthread_fd, (char *)&clientfd_tmp, 
                         sizeof(int));
                for (count = 0; count < MAX_SELECT_NUM; count++) {
                    if (all_clientfd[count] == -1) {
                        all_clientfd[count] = clientfd_tmp;
                        clientfd_sum++;
                        sprintf(temp_buf, "%s%d%s%d\n","fd:", clientfd_tmp, 
                            "接入服务端  总连接数量:", clientfd_sum);
                        input_buffer(temp_buf);
                        printf("fd--%d接入服务端  总连接数量--%d\r\n", 
                                clientfd_tmp, clientfd_sum);
                        if (clientfd_tmp > maxfd)
                            maxfd = clientfd_tmp;
                        clientfd_tmp = -1;
                        break;
                    }
                }
                if (clientfd_sum == MAX_SELECT_NUM && 
                    ring_buffer_len(to_recv_pthread_fd) >= sizeof(int)) {
                    DEBUG("过多用户登入\r\n");
                    break;
                }
            }
        } else
            DEBUG("过多用户登入\r\n");
        /*监听客户端有没数据发送过来*/
        ret = select(maxfd + 1, &all_setfd, NULL, NULL, &timeout);

        /*如果没有心跳包发过来，则认为客户端掉线，关闭socket*/
        time(&now_time);
        for (i = 0; i <= 10; i++) {
            if (app.heart_bag.is_data[i] == 1) {
                /*如果上次的时间和当前时间相差10s，则认为客户端掉线*/
                if ((now_time - app.heart_bag.last_heart_time[i]) > 10) {
                    for (count = 0; count < MAX_SELECT_NUM; count++) {
                        if (all_clientfd[count] == app.heart_bag.heart_fd[i]) {
                            break;
                        }
                    }
                    app.heart_bag.heart_fd[i] = 0;
                    app.heart_bag.last_heart_time[i] = 0;
                    app.heart_bag.is_data[i] = 0;

		    if (clientfd_sum > 0) {
                    	close(all_clientfd[count]);
                    	FD_CLR(all_clientfd[count], &all_setfd);
                    	clientfd_sum--;
                    	sprintf(temp_buf, "%s%d%s%d\r\n","用户fd:", all_clientfd[count], 
                            "断开 总连接数量:", clientfd_sum);
                    	input_buffer(temp_buf);
                    	printf("用户fd--%d断开 总连接数量--%d\r\n",
                            all_clientfd[count], clientfd_sum);
                    	data_tmp.clientfd = all_clientfd[count];
                    	all_clientfd[count] = -1;
                    	maxfd = 0;
                    	for (count1 = 0; count1 < MAX_SELECT_NUM; count1++) {
                            if (all_clientfd[count1] > maxfd)
                            	maxfd = all_clientfd[count1];
                    	}

                    	/*重新将fd加入到监听行列*/
                    	FD_ZERO(&all_setfd);
                    	for (count = 0; count < MAX_SELECT_NUM; count++) {
                            if (all_clientfd[count] != -1)
                            	FD_SET(all_clientfd[count], &all_setfd);
                    	}
                    	should_continue = 1;
                    	last_fd_is_disconnect = 1;
		    }
                }
                break;
            }
        }

        /*执行心跳包超市处理之后，重新进行循环*/
        if (should_continue == 1) {
            should_continue = 0;
            continue;
        }

        if (ret < 0) {
            DEBUG("SELECT FAIL!\r\n");
            continue;
        } 
        if (ret == 0) {
            /* select超时后，重新循环 */
            FD_ZERO(&all_setfd);
            for (count = 0; count < MAX_SELECT_NUM; count++) {
                if (all_clientfd[count] != -1)
                    FD_SET(all_clientfd[count], &all_setfd);
            }

            timeout.tv_sec = 1;
            timeout.tv_usec = 0;
            continue;
        }

        /*找到可以读的fd*/
        for (count = 0; count < MAX_SELECT_NUM; count++) {
            if (all_clientfd[count] != -1 &&
                FD_ISSET(all_clientfd[count], &all_setfd)) {

                communication.data.recvfd = all_clientfd[count];
                /* select监听到有数据发送过来后，开始接收数据 */
                ret = communication.ioctl(&communication.dev, 
                                   communication.dev.cmd, communication.dev.arg);
                if (ret == COMM_GET_ACK) {
                    continue;
                }
                    
                /*接收失败，客户端已断开连接*/
                if (ret < 0) {
                    if (last_fd_is_disconnect != 1 && clientfd_sum > 0) {
                        close(all_clientfd[count]);
                        FD_CLR(all_clientfd[count], &all_setfd);
                        clientfd_sum--;
                        sprintf(temp_buf, "%s%d%s%d\r\n", "fd:", all_clientfd[count],
                                "断开 总连接数量:", clientfd_sum);
                        input_buffer(temp_buf);
                        printf("fd--%d断开 总连接数量--%d\r\n",
                                all_clientfd[count], clientfd_sum);
                        data_tmp.clientfd = all_clientfd[count];
                        all_clientfd[count] = -1;
                        maxfd = 0;
                        for (count1 = 0; count1 < MAX_SELECT_NUM; count1++) {
                            if(all_clientfd[count1] > maxfd)
                                maxfd = all_clientfd[count1];
                        }
                        reset_data_packet(&data_tmp.data);

                        last_fd_is_disconnect = 0;
                    }
                } else {
                    /*接收成功，将数据写入缓冲区*/ 
                    cpy_data_packet(&data_tmp.data, &communication.data.recv_data_packet);
                    data_tmp.clientfd = all_clientfd[count];
                    ring_buffer_put(recv_data, (char *)&data_tmp,
                            sizeof(struct data_with_fd));
                    reset_data_packet(&data_tmp.data);
                    free_data_packet(&communication.data.recv_data_packet);
                }
            }
        }

        /*重新将fd加入到监听行列*/
        FD_ZERO(&all_setfd);
        for (count = 0; count < MAX_SELECT_NUM; count++) {
            if (all_clientfd[count] != -1)
                FD_SET(all_clientfd[count], &all_setfd);
        }
    }
}

/**
 * @brief	从recv_data数据缓冲区获取需要处理的信息进行相应的处理    
 * @param	app--总结构体，里面有工作线程所需要处理的数据
 * @return	-APP_PARAM_NULL        入口参数为空
 *
 * @note:相关命令的定义在communication_protocol.h
 */
void *server_work_thread(void *arg)
{
    struct ring_buffer *recv_data = NULL;
    struct data_with_fd data_tmp;
    struct communication_core communication;
    char temp_buf[100] = {0};
    char ticket_buffer_6[10000] = {0};
    char ticket_buffer_4[10000] = {0};
    char ticket_buffer_3[10000] = {0};
    char ticket_buffer_2[10000] = {0};
    char ticket_buffer[20000] = {0};
    char user_buffer[10000] = {0};
    int ret;
    struct list_head temporary_head;
    struct list_head *pos = NULL, *n = NULL;
    struct user_ticket *scan_list = NULL;
    struct ticket *scan_list_2 = NULL;
    time_t now_time;
    char ack;
    int i;

    communication_core_init(&communication);

    recv_data = app.ring_buffers.recv_data;
    reset_data_packet(&data_tmp.data);
    data_tmp.clientfd = -1;

    while (1) {
        /*接收缓冲区的数据并进行处理*/
        ring_buffer_get(recv_data, (char *)&data_tmp, 
                         sizeof(struct data_with_fd));
        switch (data_tmp.data.cmd) {
            case HEART_CMD:
                sprintf(temp_buf, "%s%d%s\r\n", "fd:", data_tmp.clientfd,
                                ",发送心跳包");
                input_buffer(temp_buf);
                printf("fd:%d,发送心跳包\n", data_tmp.clientfd);
                for (i = 0; i < 10; i++) {
                    if (app.heart_bag.heart_fd[i] == data_tmp.clientfd) {
                        break;
                    }
                }
                time(&now_time);
                app.heart_bag.last_heart_time[i] = now_time;
                break;

            case REGISTER_CMD:
                sprintf(temp_buf, "%s%d%s\r\n", "fd:", data_tmp.clientfd,
                                ",请求注册账号");
                input_buffer(temp_buf);
                printf("fd:%d,请求注册账号\n", data_tmp.clientfd);
                sem_wait(&sem_user);
                sleep(1);
                user_register(data_tmp.data, data_tmp.clientfd, (app).interaction);
                sleep(1);
                sem_post(&sem_user);
                break;

            case LOGIN_CMD:
                sprintf(temp_buf, "%s%d%s\r\n", "fd:", data_tmp.clientfd,
                                ",请求登录");
                input_buffer(temp_buf);
                printf("fd:%d,请求登录\n", data_tmp.clientfd);
                sem_wait(&sem_user);
                sleep(1);
                user_login(data_tmp.data, data_tmp.clientfd, (app).interaction);
                sleep(1);
                sem_post(&sem_user);
                break;
            
            case FIND_TICKET_CMD:
                sprintf(temp_buf, "%s%d%s\r\n", "fd:", data_tmp.clientfd,
                                ",请求查询12306车票");
                input_buffer(temp_buf);
                printf("fd:%d,请求查询12306车票\n", data_tmp.clientfd);
                sem_wait(&sem_find_ticket);
                sleep(1);
                get_ticket_from_py(data_tmp.data, data_tmp.clientfd, ticket_buffer);
		printf("ticket_buffer size:%ld", strlen(ticket_buffer));
                send_ticket_to_app(ticket_buffer, data_tmp.clientfd);
                for (i = 0; i < 20000; i++) {
                    ticket_buffer[i] = 0;
                }
                sleep(1);
                sem_post(&sem_find_ticket);

                break;

            case CHANGE_FIND_TICKET_CMD:
                sprintf(temp_buf, "%s%d%s\r\n", "fd:", data_tmp.clientfd,
                                ",请求查看车票");
                input_buffer(temp_buf);
                printf("fd:%d,请求查看车票\n", data_tmp.clientfd);
                sem_wait(&sem_find_ticket);
                sem_wait(&sem_ticket);
                sleep(1);
                build_all_ticket_buffer(ticket_buffer_4, &((app).interaction->ticket_head));
                send_ticket_to_app(ticket_buffer_4, data_tmp.clientfd);
                for (i = 0; i < 10000; i++) {
                    ticket_buffer_4[i] = 0;
                }
                sleep(1);
                sem_post(&sem_find_ticket);
                sem_post(&sem_ticket);

                break;
            
            case BUY_TICEKT_CMD:
                sprintf(temp_buf, "%s%d%s\r\n", "fd:", data_tmp.clientfd,
                                ",请求购买车票");
                input_buffer(temp_buf);
                printf("fd:%d,请求购买车票\n", data_tmp.clientfd);
                sem_wait(&sem_user_ticket);
                sem_wait(&sem_user);
                sleep(1);
                buy_ticket(data_tmp.data, data_tmp.clientfd, &((app).interaction->ticket_head),
                            &((app).interaction->user_ticket_head), &((app).interaction->user_head));
                sleep(1);
                sem_post(&sem_user_ticket);
                sem_post(&sem_user);
                break;
            
            case FIND_ORDER_CMD:
                sprintf(temp_buf, "%s%d%s\r\n", "fd:", data_tmp.clientfd,
                                ",请求查看订单");
                input_buffer(temp_buf);
                printf("fd:%d,请求查看订单\n", data_tmp.clientfd);
                sem_wait(&sem_user_ticket);
                sleep(1);
                init_list_head(&temporary_head);
                ret = find_order(data_tmp.data, data_tmp.clientfd, 
                                &((app).interaction->user_ticket_head), &temporary_head);
                if (ret == true) {
                    build_ticket_buffer(ticket_buffer_2, &temporary_head);
                    send_ticket_to_app(ticket_buffer_2, data_tmp.clientfd);
                    for (i = 0; i < 10000; i++) {
                        ticket_buffer_2[i] = 0;
                    }
                } else {
                    ack = NO_FIND_TICKET_ACK;
                    send_ack(data_tmp.clientfd, ack);
                }

                list_for_each_safe (pos, n, &temporary_head) {
                    scan_list = list_entry(pos, struct user_ticket, list);
                    list_del(pos);
                    free(scan_list);
                }

                scan_list = NULL;
                pos = NULL;
                n = NULL;
                sleep(1);
                sem_post(&sem_user_ticket);
                break;

            case RETURN_TICKET_CMD:
                sprintf(temp_buf, "%s%d%s\r\n", "fd:", data_tmp.clientfd,
                                ",请求退票");
                input_buffer(temp_buf);
                printf("fd:%d,请求退票\n", data_tmp.clientfd);
                sem_wait(&sem_user_ticket);
                sleep(1);
                ret = return_ticket(data_tmp.data, data_tmp.clientfd, &((app).interaction->user_ticket_head), &((app).interaction->ticket_head));
                if (ret == TRUE) {
                    ack = RETURN_TICKET_SUCCESS_ACK;
                    send_ack(data_tmp.clientfd, ack);
                } else {
                    ack = NO_FIND_TICKET_ACK;
                    send_ack(data_tmp.clientfd, ack);
                }
                sleep(1);
                sem_post(&sem_user_ticket);
                break;

            case ADMIN_ALL_ORDER:
                sprintf(temp_buf, "%s%d%s\r\n", "fd:", data_tmp.clientfd,
                                ",请求查看本地所有的车票");
                input_buffer(temp_buf);
                printf("fd:%d,请求查看本地所有的车票\n", data_tmp.clientfd);
                sem_wait(&sem_ticket);
                sleep(1);
                build_all_ticket_buffer(ticket_buffer_6, &((app).interaction->ticket_head));
                send_ticket_to_app(ticket_buffer_6, data_tmp.clientfd);
                for (i = 0; i < 10000; i++) {
                    ticket_buffer_6[i] = 0;
                }
                sleep(1);
                sem_post(&sem_ticket);
                break;

            case ADMIN_ALL_USER:
                sprintf(temp_buf, "%s%d%s\r\n", "fd:", data_tmp.clientfd,
                                ",请求查看所有的用户信息");
                input_buffer(temp_buf);
                printf("fd:%d,请求查看所有的用户信息\n", data_tmp.clientfd);
                sem_wait(&sem_user);
                sleep(1);
                build_all_user_buffer(user_buffer, &((app).interaction->user_head));
                send_ticket_to_app(user_buffer, data_tmp.clientfd);
                for (i = 0; i < 10000; i++) {
                    user_buffer[i] = 0;
                }
                sleep(1);
                sem_post(&sem_user);
                break;

            case ADMIN_ADD_TICEKT:
                sprintf(temp_buf, "%s%d%s\r\n", "fd:", data_tmp.clientfd,
                                ",请求添加车票");
                input_buffer(temp_buf);
                printf("fd:%d,请求添加车票\n", data_tmp.clientfd);
                sem_wait(&sem_ticket);
                sleep(1);
                add_ticket(data_tmp.data, data_tmp.clientfd, &((app).interaction->ticket_head));
                sleep(1);
                sem_post(&sem_ticket);
                break;
                
            case ADMIN_ADD_USER:
                sprintf(temp_buf, "%s%d%s\r\n", "fd:", data_tmp.clientfd,
                                ",请求添加用户");
                input_buffer(temp_buf);
                printf("fd:%d,请求添加用户\n", data_tmp.clientfd);
                sem_wait(&sem_user);
                sleep(1);
                add_user(data_tmp.data, data_tmp.clientfd, &((app).interaction->user_head));
                sleep(1);
                sem_post(&sem_user);
                break;

            case ADMIN_DELETE_TICKET:
                sprintf(temp_buf, "%s%d%s\r\n", "fd:", data_tmp.clientfd,
                                ",请求删除车票");
                input_buffer(temp_buf);
                printf("fd:%d,请求删除车票\n", data_tmp.clientfd);
                sem_wait(&sem_user);
                sem_wait(&sem_ticket);
                sleep(1);
                delete_ticket(data_tmp.data, data_tmp.clientfd, &((app).interaction->ticket_head), &((app).interaction->user_head));
                sleep(1);
                sem_post(&sem_user);
                sem_post(&sem_ticket);
                break;
            
            case ADMIN_DELETE_USER:
                sprintf(temp_buf, "%s%d%s\r\n", "fd:", data_tmp.clientfd,
                                ",请求删除用户");
                input_buffer(temp_buf);
                printf("fd:%d,请求删除用户\n", data_tmp.clientfd);
                sem_wait(&sem_user);
                sleep(1);
                delete_user(data_tmp.data, data_tmp.clientfd, &((app).interaction->user_head));
                sleep(1);
                sem_post(&sem_user);
                break;
            
            case ADMIN_CHANGE_TICKET:
                sprintf(temp_buf, "%s%d%s\r\n", "fd:", data_tmp.clientfd,
                                ",请求修改车票信息");
                input_buffer(temp_buf);
                printf("fd:%d,请求修改车票信息\n", data_tmp.clientfd);
                sem_wait(&sem_user_ticket);
                sem_wait(&sem_ticket);
                sleep(1);
                change_ticket(data_tmp.data, data_tmp.clientfd, &((app).interaction->ticket_head), &((app).interaction->user_ticket_head));
                sleep(1);
                sem_post(&sem_ticket);
                sem_post(&sem_user_ticket);
                break;

            case ADMIN_CHANGE_USER:
                sprintf(temp_buf, "%s%d%s\r\n", "fd:", data_tmp.clientfd,
                                ",请求修改用户信息");
                input_buffer(temp_buf);
                printf("fd:%d,请求修改用户信息\n", data_tmp.clientfd);
                sem_wait(&sem_user);
                sleep(1);
                change_user(data_tmp.data, data_tmp.clientfd, &((app).interaction->user_head));
                sleep(1);
                sem_post(&sem_user);
                break;

            case USER_FIND_TICKET:
                sprintf(temp_buf, "%s%d%s\r\n", "fd:", data_tmp.clientfd,
                                ",请求查看车票");
                input_buffer(temp_buf);
                printf("fd:%d,请求查看车票\n", data_tmp.clientfd);
                sem_wait(&sem_ticket);
                sleep(1);
                init_list_head(&temporary_head);
                ret = user_find_ticket(data_tmp.data, data_tmp.clientfd, &((app).interaction->ticket_head), ticket_buffer_3);
                if (ret == true) {
                    send_ticket_to_app(ticket_buffer_3, data_tmp.clientfd);
                } else {
                    ack = NO_FIND_TICKET_ACK;
                    send_ack(data_tmp.clientfd, ack);
                }

                list_for_each_safe (pos, n, &temporary_head) {
                    scan_list_2 = list_entry(pos, struct ticket, list);
                    list_del(pos);
                    free(scan_list_2);
                }

                for (i = 0; i < 10000; i++) {
                    ticket_buffer_3[i] = 0;
                }
                scan_list_2 = NULL;
                pos = NULL;
                n = NULL;
                sleep(1);
                sem_post(&sem_ticket);
                break;
        }

        reset_data_packet(&communication.data.send_data_packet);
        free_data_packet(&data_tmp.data);
        data_tmp.clientfd = -1;
    }
    return arg;
}

/**
 * @brief   按下Ctrl+c时触发信号函数
 */
static void deal_ctrl_c(int sig)
{
    destroy();
}

void destroy(void)
{
    system("clear");
    sem_post(&sem_destroy1);
    /*等待销毁线程执行完销毁程序*/
    pthread_join(app.server_pthreads.destroy_thread, NULL);
    longjmp(buf, 1);
}
